import GridLayer from '../../layer/GridLayer';
import KBarLayer from '../../layer/KBarLayer';
import Canvas from '../../core/Canvas';
import Event from '../../event/Event';
import AccelerateAction from '../../action/AccelerateAction';
import Layer from '../../core/Layer';
import YAxisLayer from './YAxisLayer';
import XAxisLayer from './XAxisLayer';
import { formatDate } from '../../utils/date';
import PriceLineLayer from './PriceLineLayer';
import CrossLayer from './CrossLayer';

export default class extends Layer{
    constructor(canvas, style, data = []) {
        super(canvas, style);
        this.data = data || [];
        this.style = style;
        const xFontSize = (style.xAxisFontSize || Number(this.fontSize)) + 10;
        this.xFontSize = xFontSize;
        this.grid = new GridLayer(this.canvas, {
            rows: style.rows || 5,
            cols: style.cols || 5,
            height: `calc(100% - ${xFontSize}px)`,
            width: '100%',
            left: 0,
            bottom: `${xFontSize}px`,
            position: 'absolute',
            color: style.axisColor || '#D3D3D3',
            lineWidth: 1,
            lineDash: [8, 4, 8],
        });
        this.kbarLayer = new KBarLayer(this.canvas, {
            left: 0,
            width: '100%',
            height: `calc(100% - ${xFontSize + 128}px)`,
            bottom: `${xFontSize + 64}px`,
            position: 'absolute',
            barNum: style.barNum || 80,
        }, data);
        const yAxisAlign = style.yAxisAlign || 'left';
        this.yAxisLayer = new YAxisLayer(this.canvas, {
            fontSize: style.yAxisFontSize || this.fontSize,
            fontFamily: style.yAxisFontFamily || this.fontFamily,
            color: style.yAxisColor || this.color,
            textAlign: yAxisAlign,
            left: 0,
            bottom: `${xFontSize}px`,
            width: '100%',
            height: `calc(100% - ${xFontSize}px)`,
            position: 'absolute',
        }, []);
        this.xAxisLayer = new XAxisLayer(this.canvas, {
            fontSize: style.xAxisFontSize || this.fontSize,
            fontFamily: style.xAxisFontFamily || this.fontFamily,
            color: style.xAxisColor || this.color,
            left: 0,
            bottom: '5px',
            width: '100%',
            position: 'absolute',
            cols: style.cols || 5,
        });
        this.kbarLayer.addEventListener(Event.EVENT_DRAG, (e) => {
            if (this.kbarLayer.locked) {
                return;
            }
            this.barDragFlag = true;
            if (
                this.kbarLayer.xShift + e.distanceX
                >= (this.kbarLayer.data.length - this.kbarLayer.barNum) * this.kbarLayer.width / this.kbarLayer.barNum
            ) {
                this.kbarLayer.xShift = (this.kbarLayer.data.length - this.kbarLayer.barNum) * this.kbarLayer.width / this.kbarLayer.barNum;
            } else if (this.kbarLayer.xShift <= -this.kbarLayer.width / 2) {
                this.kbarLayer.xShift = - this.kbarLayer.width / 2;
            } else {
                this.kbarLayer.xShift = this.kbarLayer.xShift + e.distanceX;
            }
            this.canvas.paint();
        });
        this.kbarLayer.addEventListener(Event.EVENT_DRAG_END, (e) => {
            if (this.kbarLayer.locked && !this.barDragFlag) {
                return;
            }
            this.barDragFlag = false;
            const barWidth = this.kbarLayer.width / this.kbarLayer.barNum;
            const accelerate = e.speedX > 0 ?  barWidth * 1000 : -barWidth * 1000;
            const duration = Math.abs(e.speedX / accelerate);
            if (duration < 0.06) {
                return;
            }
            this.accelerateAction = new AccelerateAction(duration, {
                speedX: e.speedX,
                accelerateX: accelerate,
            });
            this.kbarLayer.runAction(this.accelerateAction, (node, action) => {
                if (node.xShift <= this.kbarLayer.width / 2) {
                    node.stopAction(action);
                }
            });
        });
        this.priceLineLayer = new PriceLineLayer(this.canvas, {
            fontSize: style.yAxisFontSize || this.fontSize,
            fontFamily: style.yAxisFontFamily || this.fontFamily,
            fontColor: style.priceColor || this.color,
            color: style.yAxisColor || this.color,
            width: '100%',
            height: `calc(100% - ${xFontSize}px)`,
            position: 'absolute',
            bottom: `${xFontSize}px`,
        }, '');
        this.crossLayer = new CrossLayer(this.canvas, {
            width: '100%',
            height: `100%`,
            position: 'absolute',
            color: style.crossColor || this.color,
            fontColor: style.crossFontColor || this.color,
            left: 0,
            bottom: 0,
        });
        this.crossLayer.onCrossing = (bar, pos) => {
            if (this.onSelect) {
                const indicators = [];
                for (let i = 0; i < this.kbarLayer.indicatorLayers.length; i++) {
                    indicators.push(this.kbarLayer.indicatorLayers[i].getIndicator(pos));
                }
                this.onSelect({
                    ...bar,
                    indicators,
                });
            }
        }
        this.crossLayer.onCrossStart = () => {
            this.kbarLayer.locked = true;
        }
        this.crossLayer.onCrossEnd = () => {
            this.kbarLayer.locked = false;
        }
        this.kbarLayer.onBuilded = (node, { max, min, xStep, yStep, start, end }) => {
            const diff = (this.grid.height - this.kbarLayer.height) / this.kbarLayer.height * (max - min) / 2;
            const axisMin = min - diff;
            const axisMax = max + diff;
            const { rows = 5, cols = 5, yAxisDecimal = 4, xAxisFormatter = 'yyyy-MM-dd', xAxisFontSize } = this.style;
            const yAxisStep = (axisMax - axisMin) / (rows + 1);
            const yData = [];
            for (let i = 0; i <= rows; i++) {
                yData.push((axisMin + i * yAxisStep).toFixed(yAxisDecimal));
            }
            this.yAxisLayer.data = yData;
            const { data = [], barNum } = node;
            const dataLen = Math.floor((end - start) / barNum * cols);
            const xLen = Math.floor(barNum / cols);
            const xFontSize = (xAxisFontSize || Number(this.fontSize)) + 10;
            const xData = [];
            for (let i = 0; i <= dataLen; i++) {
                xData.push(formatDate(new Date(data[start + i * xLen].datetime), xAxisFormatter));
            }
            if (xLen < cols) {
                xData.push(formatDate(new Date(data[end].datetime), xAxisFormatter));
            }
            this.xAxisLayer.data = xData;
            const priceY = Math.round((data[data.length - 1].close - axisMin) * yStep);
            this.priceLineLayer.text = data[data.length - 1].close;
            this.priceLineLayer.baseY = priceY;
            this.crossLayer.data = data;
            this.crossLayer.start = start;
            this.crossLayer.end = end;
            this.crossLayer.xStep = xStep;
            this.crossLayer.yStep = yStep;
            this.crossLayer.min = axisMin;
            this.crossLayer.baseY = xFontSize;
            this.crossLayer.xFormatter = (val) => formatDate(new Date(val), xAxisFormatter);
            this.crossLayer.yFormatter = (val) => Number(val).toFixed(yAxisDecimal);
        };
    }
    addIndicator(indicatorLayer) {
        if (indicatorLayer instanceof IndicatorLayer) {
            this.kbarLayer.indicatorLayers.push(indicatorLayer);
        }
    }
    build(paint) {
        this.childs.splice(0, this.childs.length);
        this.addChild(
            this.grid,
            this.kbarLayer,
            this.yAxisLayer,
            this.xAxisLayer,
            this.priceLineLayer,
            this.crossLayer,
        );
    }
}

export class IndicatorLayer extends Layer {
    constructor(canvas, style, options = { data: [], params: {}, name: '' }) {
        super(canvas, style);
        const { data = [], params = {}, name = '' } = options;
        this.data = data;
        this.params = params;
        this.name = name;
        this.dataStart = style.dataStart || 0;
        this.dataEnd = style.dataEnd || data.length;
        this.min = Number.MAX_VALUE;
        this.max = Number.MIN_VALUE;
    }

    caculate() {

    }

    render() {

    }

    getIndicator(pos) {
        return {
            name: this.name,
            value: '',
        };
    }
}

export class QuoteLayer extends Layer {
    constructor(canvas, style, options = { data: [], params: {}, name: '' }) {
        super(canvas, style);
        const  { data = [], params = {}, name = '' } = options;
        this.data = data;
        this.params = params;
        this.name = name;
        this.dataStart = style.dataStart || 0;
        this.dataEnd = style.dataEnd || data.length;
    }

    render() {
        
    }

    getQuote(pos) {
        return {
            name: this.name,
            value: '',
        };
    }


}
